import java.util.Arrays;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;

/**
 * @author Wang Chen Peng
 * @date 2019/01/09
 * describe:两数之和
 * https://leetcode-cn.com/problems/two-sum/submissions/
 */
public class twoSum {

    public static void main(String[] args) {
        //int[] raw = {2,5,5,11};
        int[] raw = new int[]{3, 3};
        int target = 6;
        long startTime = System.currentTimeMillis();
        int[] ints = twoSum4(raw, target);
        System.out.println(System.currentTimeMillis() - startTime);
        System.out.println(Arrays.toString(ints));
    }

    /**
     * 失败的尝试
     */
    static int[] twoSum2(int[] nums, int target) {
        AtomicInteger x = new AtomicInteger(0);
        final int[] aaa = new int[2];
        int length = nums.length - 1;

        int xvalue = x.addAndGet(1);
        IntStream.rangeClosed(xvalue + 1, length).parallel().forEach(intstream -> {
            if (nums[xvalue] + nums[intstream] == target) {
                //return new int[]{xvalue,intstream};
                aaa[0] = xvalue;
                aaa[1] = intstream;
            }
        });

        return aaa;
    }

    /**
     * 暴力法
     */
    static int[] twoSum1(int[] nums, int target) {

        int[] result = new int[2];

        for (int x = 0; x < nums.length; x++) {
            for (int y = x + 1; y < nums.length; y++) {
                if (nums[x] + nums[y] == target) {
                    result[0] = x;
                    result[1] = y;
                    return result;
                }
            }
        }

        return null;
    }

    /**
     * 两边哈希表
     */
    static int[] twoSum3(int[] nums, int target) {
        //空间换时间
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], i);
        }
        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            //此处 因为如果数组中两数一样 则会key冲突则会覆盖value get时则会获取到第二数据的下标
            if (map.containsKey(complement) && map.get(complement) != i) {
                return new int[]{i, map.get(complement)};
            }
        }
        throw new IllegalArgumentException("No two sum solution");
    }

    /**
     * 一遍哈希表
     */
    static int[] twoSum4(int[] nums, int target) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int index=0;index<nums.length;index++){
            int value = target-nums[index];
            //先判断则是避免获取到自己的下标 程序出错
            if (map.containsKey(value)&&map.get(value)!=index){
                return new int[]{map.get(value),index};
            }
            map.put(nums[index],index);
        }
        return null;
    }

}
